/*
* This file is a part of the open-eBackup project.
* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
* If a copy of the MPL was not distributed with this file, You can obtain one at
* http://mozilla.org/MPL/2.0/.
*
* Copyright (c) [2024] Huawei Technologies Co.,Ltd.
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
*/
#include "HCSProtectEngine.h"
#include "volume_handlers/oceanstor/OceanStorVolumeHandler.h"
#include "volume_handlers/fusionstorage/FusionStorageVolumeHandler.h"

using namespace OpenStackPlugin;

namespace  {
    const int32_t VM_NOT_EXSIT = 1577213594;
    const int CONSTANT_NUM_6 = 6;
} /* namespace  */

namespace HcsPlugin {

int32_t HCSProtectEngine::CheckPreSnapshotExist(const VirtPlugin::JobTypeParam &jobTypeParam)
{
    m_appEnv = jobTypeParam.m_job.protectEnv;
    m_hcsOpServiceUtils.GetAppEnv(m_appEnv);
    int retryTimes = 1;
    int curConsumeRetryTimes = 0;
    for (const VolSnapInfo &snapshot : jobTypeParam.m_snapshotInfo.m_volSnapList) {
        if (ConfirmIfSnapDeleted(snapshot.m_snapshotId, retryTimes, curConsumeRetryTimes)) {
            ERRLOG("Snapshot %s is not exist.", snapshot.m_snapshotId.c_str());
            return FAILED;
        }
    }
    return SUCCESS;
}

int32_t HCSProtectEngine::GetMachineMetadata(VMInfo &vmInfo)
{
    if (!DoGetMachineMetadata()) {
        ERRLOG("Get machine metadata failed, %s", m_taskId.c_str());
        return FAILED;
    }
    vmInfo = m_vmInfo;
    return SUCCESS;
}

int32_t HCSProtectEngine::AllowDelCopyInLocalNode(const AppProtect::DelCopyJob &job, ActionResult& returnValue)
{
    m_appEnv = job.protectEnv;
    m_application = job.protectObject;
    int32_t errorCode = 0;
    if (CheckEnvConnection(job.protectEnv, job.protectObject.id, errorCode) != SUCCESS && errorCode != VM_NOT_EXSIT) {
        ERRLOG("Check env connection failed;");
        returnValue.__set_bodyErr(errorCode);
        returnValue.__set_code(errorCode);
        returnValue.__set_message("Check connect failed.");
        return FAILED;
    }
    return SUCCESS;
}

int32_t HCSProtectEngine::AllowDelCopySubJobInLocalNode(const AppProtect::DelCopyJob& job,
    const AppProtect::SubJob& subJob, ActionResult& returnValue)
{
    m_appEnv = job.protectEnv;
    m_application = job.protectObject;
    int32_t errorCode = 0;
    if (CheckEnvConnection(job.protectEnv, job.protectObject.id, errorCode) != SUCCESS && errorCode != VM_NOT_EXSIT) {
        ERRLOG("Check env connection failed;");
        returnValue.__set_bodyErr(errorCode);
        returnValue.__set_code(errorCode);
        returnValue.__set_message("Check connect failed.");
        return FAILED;
    }
    return SUCCESS;
}

int32_t HCSProtectEngine::DeleteSnapshotPreHookInPacific(const VolSnapInfo &volSnap,
    std::shared_ptr<VolumeHandler> storageVolHandler)
{
    std::shared_ptr<FusionStorageVolumeHandler> fusionStorageVolHandler =
        std::dynamic_pointer_cast<FusionStorageVolumeHandler>(storageVolHandler);
    Json::Value itemJson;
    std::string volumeName;
    std::string attachedVolumes;
    int32_t result;
    fusionStorageVolHandler->DetachVolume(itemJson, volSnap.m_storageSnapId, attachedVolumes, result);
    if (volSnap.m_snapshotDescription.find("_Time:") != std::string::npos) {
        int32_t pos = volSnap.m_snapshotDescription.find("_Time:");
        std::string extenInfo = "_" + volSnap.m_snapshotDescription.substr(pos + CONSTANT_NUM_6) + "_BITMAP";
        std::string bitmapName = volSnap.m_storageSnapId + extenInfo;
        std::string erro;
        fusionStorageVolHandler->m_spBitmapHandle->DeleteAndDetachapVolume(bitmapName, erro);
    }
    return SUCCESS;
}
 
int32_t HCSProtectEngine::DeleteSnapshotPreHookInDorado(const VolSnapInfo &volSnap,
    std::shared_ptr<VolumeHandler> storageVolHandler)
{
    std::shared_ptr<OceanStorVolumeHandler> doradoVolHandler =
        std::dynamic_pointer_cast<OceanStorVolumeHandler>(storageVolHandler);
    std::string errorDes;
    if (doradoVolHandler->m_spApiOperator->RemovedObjFromAllLunGroup(volSnap.m_storageSnapId,
        MO_SNAPSHOT, errorDes) != Module::SUCCESS) {
        ERRLOG("Delete mapping set failed");
        return FAILED;
    }
    return SUCCESS;
}
}